#include "http_session.h"
#include "http_parser.h"

namespace framework
{
namespace http
{

HttpSession::HttpSession(Socket::ptr sock, bool owner)
:SocketStream(sock, owner) {}

//接收HTTP请求
HttpRequest::ptr HttpSession::recvRequest()
{
    HttpRequestParser::ptr parser(new HttpRequestParser); //http请求类解析
    //获取HttpResponse协议的最大消息体大小
    uint64_t buff_size = HttpResponseParser::GetHttpRequestBufferSize();
    std::shared_ptr<char> buffer(new char[buff_size], [](char* ptr){
        delete[] ptr; //指定删除器
    });

    char* data = buffer.get();
    int offset = 0; //剩余没有解析的字符数
    do
    {
        int len = read(data + offset, buff_size - offset); //SocketStream::read 读数据
        if(len <= 0)
        {
            return nullptr;
        }
        len += offset;
        //解析协议，已经解析的数据被删除 返回实际解析的长度
        size_t nparse = parser->execute(data, len); 
        if(parser->hasError())
        {
            close();
            return nullptr;
        }
        offset = len - nparse;
        if(offset >= (int)buff_size) //剩余解析数据的长度>=buff_size
        {
            close();
            return nullptr;
        }
        if(parser->isFinished())
        {
            break;
        }
    } while (true);
    int64_t length = parser->getContentLength();//获取解析后 消息体的长度
    //此时 剩余没有解析的字符数 就是消息体的长度
    if(length > 0)
    {
        std::string body;
        body.resize(length);

        int len = 0;
        if(length >= offset)
        {
            memcpy(&body[0], data, offset);
            len = offset;
        }
        else
        {
            memcpy(&body[0], data, length);
            len = length;
        }
        length -= offset;
        if(length > 0)  //如果还有消息体的内容没有读完
        {
            if(readFixSize(&body[len], length) <= 0) //继续读数据
            {
                close();
                return nullptr;
            }
        }
        parser->getData()->setBody(body);
    }
    parser->getData()->init();
    return parser->getData();
}

//发送HTTP响应
int HttpSession::sendResponse(HttpResponse::ptr rsp)
{
    std::stringstream ss;
    ss << *rsp;
    std::string data = ss.str();
    //发送定长度的数据
    return writeFixSize(data.c_str(), data.size());
}


} // namespace http
} // namespace framework